package se.webbzon.boltzmann.game.event;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import se.webbzon.boltzmann.environment.AbstractEnvironment;
import se.webbzon.boltzmann.game.object.dialogue.DialogueBackground;
import se.webbzon.boltzmann.game.object.dialogue.layout.DefaultSimpleDialogueLayout;
import se.webbzon.boltzmann.game.object.dialogue.layout.SimpleDialogueLayout;
import se.webbzon.boltzmann.game.object.player.AbstractPlayerCharacter;
import se.webbzon.boltzmann.game.sequence.Sequence;
import se.webbzon.boltzmann.game.sequence.SequenceListener;
import se.webbzon.boltzmann.game.sequence.SequenceNode;
import se.webbzon.boltzmann.game.sequence.Sequences;
import se.webbzon.boltzmann.game.sequence.builder.AbstractSequenceBinding;
import se.webbzon.boltzmann.game.sequence.builder.SequenceBuilder;
import se.webbzon.boltzmann.game.sequence.builder.SoftSequenceBinding;
import se.webbzon.boltzmann.game.sequence.builder.dialogue.SimpleDialogueRow;
import se.webbzon.boltzmann.inventory.Inventory;
import se.webbzon.boltzmann.item.AbstractItem;
import se.webbzon.boltzmann.item.ItemGroup;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldobject.WorldObject;

public class GiveItemEvent extends AbstractGameEvent {
	
	// The text lines of the dialogue
	private static final String line1 = "You got <K>@name</> <E>@name</>.#",
								line2 = "Press <A>inventory</> to show the items#",
								line3 = "in your inventory.";
	
	// A sequence listener
	private final SequenceListener listener;
	
	// The sequence associated with this game event
	private final Sequence sequence;

	/*============================================================
	Constructors
	============================================================*/
	
	/** Gives the current player the item with the id argument[0]. **/
	public GiveItemEvent(AbstractItem item, Sequence sequence) {
		this(new String[] {"" + ItemGroup.instance().getId(item)}, sequence);
	}

	/** Gives the current player the item with the id argument[0]. **/
	public GiveItemEvent(String[] arguments, Sequence sequence) {
		super(arguments);
		listener = new SequenceListenerImpl();
		this.sequence = sequence;
	}
	
	/*============================================================
	Public Methods
	============================================================*/

	@Override protected void onBegin(WorldArea world) {
		if (arguments() > 0) {
			// Retrieve the item
			final AbstractItem item;
			final Object obj = Sequences.parse(sequence, getArgument(0));
			if (obj instanceof Double) {
				item = ItemGroup.instance().getItem((int) (double) obj);
			} else {
				Collection<AbstractItem> items = ItemGroup.instance().getItems((String) obj);
				if (items.isEmpty())
					item = null;
				else
					item = items.iterator().next();
			}
			
			if (item == null)
				exception("The item with the identifier \"" + obj + "\" was not found.");
			
			// Retrieve the inventory of the player
			final AbstractPlayerCharacter player = (AbstractPlayerCharacter) sequence.getBinding(AbstractSequenceBinding.PLAYER);
			final Inventory inv = player.getPlayer().getInventory();
			inv.addItem((AbstractItem) item.clone());
			
			SequenceNode node = buildSubSequence(sequence.getEnvironment(),world,item);
			Sequence subsequence = node.getSequence();
			Map<String,WorldObject> bindings = new HashMap<String,WorldObject>();
			bindings.put("player", player);
			subsequence.begin(player.getPlayer().getInput(), node, bindings);
			subsequence.addListener(listener);
		} else
			exception("Argument exception.");
	}

	@Override protected void onEnd() {};
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** Builds the subsequence for this game event. **/
	private SequenceNode buildSubSequence(AbstractEnvironment env, WorldArea world, AbstractItem item) {
		SequenceBuilder builder = new SequenceBuilder(env);

		String text = line1.replace("@name", item.getName()) + line2 + line3;
		SimpleDialogueLayout layout = new DefaultSimpleDialogueLayout();
		SimpleDialogueRow dialogue = new SimpleDialogueRow(builder, layout, DialogueBackground.SPECIAL, text);
		dialogue.setBinding(new SoftSequenceBinding("player"));
		
		return builder.compile(world);
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	private final class SequenceListenerImpl implements SequenceListener {

		@Override public void onSequenceBegin(Sequence sequence) {};

		@Override public void onSequenceEnd(Sequence sequence) {
			end();
		}

	}

}
